use super::kline::KlineIndicator;
use super::kline::KlineMaline;
use super::malines::ma::LSMAv;
use super::malines::ma::PeriodV;
use super::FudaThing;
use chrono::DateTime;
use chrono::Duration;
use chrono::Utc;
use serde::Deserialize;
use serde::Serialize;
use std::collections::HashMap;
use surrealdb::sql::Thing;
use ts_rs::TS;

use super::indicators::IndicatorActionWrap;
use super::kline::Kline;
use super::kline::Klt;

/// for kline's indicators and malines value wrapper
#[derive(Debug, Serialize, Deserialize, TS, Clone)]
#[ts(export)]
pub enum ValueWrapper {
    /// holds indicator's value
    Float(f64),
    /// holds indicator's action
    Action(Option<IndicatorActionWrap>),
    /// holds  MA line
    MaLine(Vec<PeriodV<f64>>),
    /// holds  LSMA line
    MaLsma(Vec<PeriodV<LSMAv>>),

    /// holds  MA line
    MALines(KlineMaline),
}

#[derive(Debug, Serialize, Deserialize, Default, TS)]
#[ts(export)]
pub struct TrendLineResult {
    pub trend_line_name: String,
    /// K线详细数据变形体，通过Kline转换而来
    pub klines: Option<Vec<Kline>>,
}

/// 由于Kline的字段较多，不能通过TS宏导出，过多字段导致导致TS宏导出失败：error[E0275]:
/// overflow evaluating the requirement `impl TypeList well-formed`
/// 所以单独定义一个结构体变形体拥有较少字段，
///
/// 也为后续减少数据传输或者按需传输，
///
#[derive(Debug, Serialize, Deserialize, Default, TS, Clone)]
#[ts(export)]
pub struct KlineFlat {
    /// 唯一标识符，由security_id.klt.klts 组成唯一标识 e.g. SH.STOCK.600519.5.1709093447762 5分钟K线
    #[ts(as = "Option<FudaThing>")]
    pub id: Option<Thing>,

    /// K线的所有者Security, Record Link, Primary Key
    pub security_id: String,
    /// 周期类型 Kline Type ,参见[Klt], Primary Key
    pub klt: Klt,
    /// K线周期的开始时间, Primary Key
    pub klts: DateTime<Utc>,

    /// OHLCV开盘价
    pub open: f64,
    /// OHLCV最高价
    pub high: f64,
    /// OHLCV最低价
    pub low: f64,
    /// OHLCV收盘价
    pub close: f64,
    /// OHLCV成交量
    pub volume: u64,
    /// Indicator Summary Score，根据指标买卖不的信号及相应值得的情况，按照权重计算后总分数
    pub idc_score: Option<f64>,

    /// flatten indicators' values
    /// flatten indicators' signals
    pub map: HashMap<String, ValueWrapper>,

    ///
    /// 记录更新日期 HLC
    #[ts(as = "Option<String>")]
    pub last_updated: Option<String>,
}

// Implement the conversion from Kline to KlineFlat using the `From` trait
impl From<(&Kline, &KlineIndicator, &KlineMaline)> for KlineFlat {
    fn from(value: (&Kline, &KlineIndicator, &KlineMaline)) -> Self {
        let mut merged_map: HashMap<String, ValueWrapper> = HashMap::new(); // Start with an empty map
        let (kline, kline_indicator, kline_maline) = value;

        // <Indicators>
        match kline_indicator.adx {
            Some(ref v) =>
                merged_map.extend(
                    HashMap::from([
                        ("adx_signal0".to_string(), ValueWrapper::Action(v.signal0.to_owned())),
                        ("adx_signal1".to_string(), ValueWrapper::Action(v.signal1.to_owned())),
                        ("adx_adx".to_string(), ValueWrapper::Float(v.adx)),
                        ("adx_di_plus".to_string(), ValueWrapper::Float(v.di_plus)),
                        ("adx_di_minus".to_string(), ValueWrapper::Float(v.di_minus)),
                    ])
                ),
            None => {}
        }

        match kline_indicator.aroon {
            Some(ref v) =>
                merged_map.extend(
                    HashMap::from([
                        ("aroon_signal0".to_string(), ValueWrapper::Action(v.signal0.to_owned())),
                        ("aroon_signal1".to_string(), ValueWrapper::Action(v.signal1.to_owned())),
                        ("aroon_signal2".to_string(), ValueWrapper::Action(v.signal2.to_owned())),
                        ("aroon_up".to_string(), ValueWrapper::Float(v.up)),
                        ("aroon_down".to_string(), ValueWrapper::Float(v.down)),
                    ])
                ),
            None => {}
        }

        match kline_indicator.aso {
            Some(ref v) =>
                merged_map.extend(
                    HashMap::from([
                        ("aso_signal0".to_string(), ValueWrapper::Action(v.signal0.to_owned())),
                        ("aso_signal1".to_string(), ValueWrapper::Action(v.signal1.to_owned())),
                        ("aso_dif".to_string(), ValueWrapper::Float(v.dif)),
                    ])
                ),
            None => {}
        }

        match kline_indicator.boll {
            Some(ref v) =>
                merged_map.extend(
                    HashMap::from([
                        ("boll_signal0".to_string(), ValueWrapper::Action(v.signal0.to_owned())),
                        ("boll_upper".to_string(), ValueWrapper::Float(v.upper)),
                        ("boll_middle".to_string(), ValueWrapper::Float(v.middle)),
                        ("boll_lower".to_string(), ValueWrapper::Float(v.lower)),
                    ])
                ),
            None => {}
        }

        match kline_indicator.cci {
            Some(ref v) =>
                merged_map.extend(
                    HashMap::from([
                        ("cci_signal0".to_string(), ValueWrapper::Action(v.signal0.to_owned())),
                        ("cci_oscillator".to_string(), ValueWrapper::Float(v.oscillator)),
                    ])
                ),
            None => {}
        }

        match kline_indicator.cko {
            Some(ref v) =>
                merged_map.extend(
                    HashMap::from([
                        ("cko_signal0".to_string(), ValueWrapper::Action(v.signal0.to_owned())),
                        ("cko_oscillator".to_string(), ValueWrapper::Float(v.oscillator)),
                    ])
                ),
            None => {}
        }

        match kline_indicator.cks {
            Some(ref v) =>
                merged_map.extend(
                    HashMap::from([
                        ("cks_signal0".to_string(), ValueWrapper::Action(v.signal0.to_owned())),
                        ("cks_signal1".to_string(), ValueWrapper::Action(v.signal1.to_owned())),
                        ("cks_stop_long".to_string(), ValueWrapper::Float(v.stop_long)),
                        ("cks_source".to_string(), ValueWrapper::Float(v.source)),
                        ("cks_stop_short".to_string(), ValueWrapper::Float(v.stop_short)),
                    ])
                ),
            None => {}
        }

        match kline_indicator.cmf {
            Some(ref v) =>
                merged_map.extend(
                    HashMap::from([
                        ("cmf_signal0".to_string(), ValueWrapper::Action(v.signal0.to_owned())),
                        ("cmf_main".to_string(), ValueWrapper::Float(v.main)),
                    ])
                ),
            None => {}
        }

        match kline_indicator.cmo {
            Some(ref v) =>
                merged_map.extend(
                    HashMap::from([
                        ("cmo_signal0".to_string(), ValueWrapper::Action(v.signal0.to_owned())),
                        ("cmo_oscillator".to_string(), ValueWrapper::Float(v.oscillator)),
                    ])
                ),
            None => {}
        }

        match kline_indicator.cpc {
            Some(ref v) =>
                merged_map.extend(
                    HashMap::from([
                        ("cpc_signal0".to_string(), ValueWrapper::Action(v.signal0.to_owned())),
                        ("cpc_signal1".to_string(), ValueWrapper::Action(v.signal1.to_owned())),
                        ("cpc_signal2".to_string(), ValueWrapper::Action(v.signal2.to_owned())),
                        ("cpc_main".to_string(), ValueWrapper::Float(v.main)),
                        ("cpc_signal".to_string(), ValueWrapper::Float(v.signal)),
                    ])
                ),
            None => {}
        }

        match kline_indicator.dcc {
            Some(ref v) =>
                merged_map.extend(
                    HashMap::from([
                        ("dcc_signal0".to_string(), ValueWrapper::Action(v.signal0.to_owned())),
                        ("dcc_lower".to_string(), ValueWrapper::Float(v.lower)),
                        ("dcc_middle".to_string(), ValueWrapper::Float(v.middle)),
                        ("dcc_upper".to_string(), ValueWrapper::Float(v.upper)),
                    ])
                ),
            None => {}
        }

        match kline_indicator.dpo {
            Some(ref v) =>
                merged_map.extend(
                    HashMap::from([("dpo_dpo".to_string(), ValueWrapper::Float(v.dpo))])
                ),
            None => {}
        }

        match kline_indicator.efi {
            Some(ref v) =>
                merged_map.extend(
                    HashMap::from([
                        ("efi_signal0".to_string(), ValueWrapper::Action(v.signal0.to_owned())),
                        ("efi_main".to_string(), ValueWrapper::Float(v.main)),
                    ])
                ),
            None => {}
        }

        match kline_indicator.eom {
            Some(ref v) =>
                merged_map.extend(
                    HashMap::from([
                        ("eom_signal0".to_string(), ValueWrapper::Action(v.signal0.to_owned())),
                        ("eom_main".to_string(), ValueWrapper::Float(v.main)),
                    ])
                ),
            None => {}
        }

        match kline_indicator.evl {
            Some(ref v) =>
                merged_map.extend(
                    HashMap::from([
                        ("evl_signal0".to_string(), ValueWrapper::Action(v.signal0.to_owned())),
                        ("evl_upper".to_string(), ValueWrapper::Float(v.upper)),
                        ("evl_lower".to_string(), ValueWrapper::Float(v.lower)),
                        ("evl_source2".to_string(), ValueWrapper::Float(v.source2)),
                    ])
                ),
            None => {}
        }

        match kline_indicator.ftf {
            Some(ref v) =>
                merged_map.extend(
                    HashMap::from([
                        ("ftf_signal0".to_string(), ValueWrapper::Action(v.signal0.to_owned())),
                        ("ftf_signal1".to_string(), ValueWrapper::Action(v.signal1.to_owned())),
                        ("ftf_main".to_string(), ValueWrapper::Float(v.main)),
                        ("ftf_signal".to_string(), ValueWrapper::Float(v.signal)),
                    ])
                ),
            None => {}
        }

        match kline_indicator.hma {
            Some(ref v) =>
                merged_map.extend(
                    HashMap::from([
                        ("hma_signal0".to_string(), ValueWrapper::Action(v.signal0.to_owned())),
                        ("hma_hma".to_string(), ValueWrapper::Float(v.hma)),
                    ])
                ),
            None => {}
        }

        match kline_indicator.ikc {
            Some(ref v) =>
                merged_map.extend(
                    HashMap::from([
                        ("ikc_signal0".to_string(), ValueWrapper::Action(v.signal0.to_owned())),
                        ("ikc_signal1".to_string(), ValueWrapper::Action(v.signal0.to_owned())),
                        ("ikc_tenkan".to_string(), ValueWrapper::Float(v.tenkan)),
                        ("ikc_kijun".to_string(), ValueWrapper::Float(v.kijun)),
                        ("ikc_spana".to_string(), ValueWrapper::Float(v.spana)),
                        ("ikc_spanb".to_string(), ValueWrapper::Float(v.spanb)),
                    ])
                ),
            None => {}
        }

        match kline_indicator.kama {
            Some(ref v) =>
                merged_map.extend(
                    HashMap::from([
                        ("kama_signal0".to_string(), ValueWrapper::Action(v.signal0.to_owned())),
                        ("kama_kama".to_string(), ValueWrapper::Float(v.kama)),
                    ])
                ),
            None => {}
        }

        match kline_indicator.kdj {
            Some(ref v) =>
                merged_map.extend(
                    HashMap::from([
                        ("kdj_signal0".to_string(), ValueWrapper::Action(v.signal0.to_owned())),
                        ("kdj_signal1".to_string(), ValueWrapper::Action(v.signal1.to_owned())),
                        ("kdj_signal2".to_string(), ValueWrapper::Action(v.signal2.to_owned())),
                        ("kdj_main".to_string(), ValueWrapper::Float(v.main)),
                        ("kdj_signal".to_string(), ValueWrapper::Float(v.signal)),
                    ])
                ),
            None => {}
        }

        match kline_indicator.knc {
            Some(ref v) =>
                merged_map.extend(
                    HashMap::from([
                        ("knc_signal0".to_string(), ValueWrapper::Action(v.signal0.to_owned())),
                        ("knc_upper".to_string(), ValueWrapper::Float(v.upper)),
                        ("knc_source".to_string(), ValueWrapper::Float(v.source)),
                        ("knc_lower".to_string(), ValueWrapper::Float(v.lower)),
                    ])
                ),
            None => {}
        }

        match kline_indicator.kst {
            Some(ref v) =>
                merged_map.extend(
                    HashMap::from([
                        ("kst_signal0".to_string(), ValueWrapper::Action(v.signal0.to_owned())),
                        ("kst_kst".to_string(), ValueWrapper::Float(v.kst)),
                        ("kst_signal".to_string(), ValueWrapper::Float(v.signal)),
                    ])
                ),
            None => {}
        }

        match kline_indicator.kvo {
            Some(ref v) =>
                merged_map.extend(
                    HashMap::from([
                        ("kvo_signal0".to_string(), ValueWrapper::Action(v.signal0.to_owned())),
                        ("kvo_signal1".to_string(), ValueWrapper::Action(v.signal1.to_owned())),
                        ("kvo_main".to_string(), ValueWrapper::Float(v.main)),
                        ("kvo_signal".to_string(), ValueWrapper::Float(v.signal)),
                    ])
                ),
            None => {}
        }

        match kline_indicator.macd {
            Some(ref v) =>
                merged_map.extend(
                    HashMap::from([
                        ("macd_signal0".to_string(), ValueWrapper::Action(v.signal0.to_owned())),
                        ("macd_signal1".to_string(), ValueWrapper::Action(v.signal1.to_owned())),
                        ("macd_macd".to_string(), ValueWrapper::Float(v.macd)),
                        ("macd_signal".to_string(), ValueWrapper::Float(v.signal)),
                        ("macd_bar".to_string(), ValueWrapper::Float(v.bar)),
                    ])
                ),
            None => {}
        }

        match kline_indicator.mfi {
            Some(ref v) =>
                merged_map.extend(
                    HashMap::from([
                        ("mfi_signal0".to_string(), ValueWrapper::Action(v.signal0.to_owned())),
                        ("mfi_signal1".to_string(), ValueWrapper::Action(v.signal1.to_owned())),
                        ("mfi_upper".to_string(), ValueWrapper::Float(v.upper)),
                        ("mfi_mfi".to_string(), ValueWrapper::Float(v.mfi)),
                        ("mfi_lower".to_string(), ValueWrapper::Float(v.lower)),
                    ])
                ),
            None => {}
        }

        match kline_indicator.mti {
            Some(ref v) =>
                merged_map.extend(
                    HashMap::from([
                        ("mti_signal0".to_string(), ValueWrapper::Action(v.signal0.to_owned())),
                        ("mti_slow".to_string(), ValueWrapper::Float(v.slow)),
                        ("mti_fast".to_string(), ValueWrapper::Float(v.fast)),
                    ])
                ),
            None => {}
        }

        match kline_indicator.pcs {
            Some(ref v) =>
                merged_map.extend(
                    HashMap::from([
                        ("pcs_signal0".to_string(), ValueWrapper::Action(v.signal0.to_owned())),
                        ("pcs_upper".to_string(), ValueWrapper::Float(v.upper)),
                        ("pcs_lower".to_string(), ValueWrapper::Float(v.lower)),
                    ])
                ),
            None => {}
        }

        match kline_indicator.prs {
            Some(ref v) =>
                merged_map.extend(
                    HashMap::from([
                        ("prs_signal0".to_string(), ValueWrapper::Action(v.signal0.to_owned())),
                    ])
                ),
            None => {}
        }

        match kline_indicator.rsi {
            Some(ref v) =>
                merged_map.extend(
                    HashMap::from([
                        ("rsi_signal0".to_string(), ValueWrapper::Action(v.signal0.to_owned())),
                        ("rsi_signal1".to_string(), ValueWrapper::Action(v.signal1.to_owned())),
                        ("rsi_upper".to_string(), ValueWrapper::Float(v.upper)),
                        ("rsi_main".to_string(), ValueWrapper::Float(v.main)),
                        ("rsi_lower".to_string(), ValueWrapper::Float(v.lower)),
                    ])
                ),
            None => {}
        }

        match kline_indicator.rvi {
            Some(ref v) =>
                merged_map.extend(
                    HashMap::from([
                        ("rvi_signal0".to_string(), ValueWrapper::Action(v.signal0.to_owned())),
                        ("rvi_signal1".to_string(), ValueWrapper::Action(v.signal1.to_owned())),
                        ("rvi_main".to_string(), ValueWrapper::Float(v.main)),
                        ("rvi_signal".to_string(), ValueWrapper::Float(v.signal)),
                    ])
                ),
            None => {}
        }

        match kline_indicator.sar {
            Some(ref v) =>
                merged_map.extend(
                    HashMap::from([
                        ("sar_signal0".to_string(), ValueWrapper::Action(v.signal0.to_owned())),
                        ("sar_sar".to_string(), ValueWrapper::Float(v.sar)),
                        ("sar_trend".to_string(), ValueWrapper::Float(v.trend)),
                    ])
                ),
            None => {}
        }

        match kline_indicator.sei {
            Some(ref v) =>
                merged_map.extend(
                    HashMap::from([
                        ("sei_signal0".to_string(), ValueWrapper::Action(v.signal0.to_owned())),
                        ("sei_main".to_string(), ValueWrapper::Float(v.main)),
                        ("sei_signal".to_string(), ValueWrapper::Float(v.signal)),
                        ("sei_oscillator".to_string(), ValueWrapper::Float(v.oscillator)),
                    ])
                ),
            None => {}
        }

        match kline_indicator.tdsi {
            Some(ref v) =>
                merged_map.extend(
                    HashMap::from([
                        ("tdsi_signal0".to_string(), ValueWrapper::Action(v.signal0.to_owned())),
                        ("tdsi_signal1".to_string(), ValueWrapper::Action(v.signal1.to_owned())),
                        ("tdsi_main".to_string(), ValueWrapper::Float(v.main)),
                    ])
                ),
            None => {}
        }

        match kline_indicator.trix {
            Some(ref v) =>
                merged_map.extend(
                    HashMap::from([
                        ("trix_signal0".to_string(), ValueWrapper::Action(v.signal0.to_owned())),
                        ("trix_signal1".to_string(), ValueWrapper::Action(v.signal1.to_owned())),
                        ("trix_signal2".to_string(), ValueWrapper::Action(v.signal2.to_owned())),
                        ("trix_main".to_string(), ValueWrapper::Float(v.main)),
                        ("trix_signal".to_string(), ValueWrapper::Float(v.signal)),
                    ])
                ),
            None => {}
        }

        match kline_indicator.trsi {
            Some(ref v) =>
                merged_map.extend(
                    HashMap::from([
                        ("trsi_signal0".to_string(), ValueWrapper::Action(v.signal0.to_owned())),
                        ("trsi_signal1".to_string(), ValueWrapper::Action(v.signal1.to_owned())),
                        ("trsi_signal2".to_string(), ValueWrapper::Action(v.signal1.to_owned())),
                        ("trsi_main".to_string(), ValueWrapper::Float(v.main)),
                        ("trsi_signal".to_string(), ValueWrapper::Float(v.signal)),
                    ])
                ),
            None => {}
        }
        // </Indicators>

        // <MaLines>
        // match kline_maline {
        //     Some(ref v) => merged_map.extend(HashMap::from([(
        //         "malines".to_string(),
        //         ValueWrapper::MALines(v.to_owned()),
        //     )])),
        //     None => {}
        // };

        // </MaLines>

        KlineFlat {
            id: kline.id.to_owned(),
            security_id: kline.security_id.to_owned(),
            klt: kline.klt,
            klts: kline.klts,
            open: kline.open,
            high: kline.high,
            low: kline.low,
            close: kline.close,
            volume: kline.volume,
            idc_score: kline_indicator.idc_score,
            map: merged_map,

            last_updated: kline.last_updated.to_owned(),
        }
    }
}

pub fn interpolate_missing_klines(kline_vec: &Vec<KlineFlat>) -> Vec<KlineFlat> {
    let mut interpolated_klines = Vec::new();
    let mut previous_kline: Option<KlineFlat> = None;

    for current_kline in kline_vec.into_iter() {
        if let Some(prev) = previous_kline.take() {
            match prev.klt {
                Klt::M005 => {
                    // Interpolate for M005
                    interpolate_gaps(
                        &prev,
                        &current_kline,
                        Klt::M005,
                        Duration::minutes(5),
                        &mut interpolated_klines
                    );
                }
                Klt::M001 => {
                    // Interpolate for M001
                    interpolate_gaps(
                        &prev,
                        &current_kline,
                        Klt::M001,
                        Duration::minutes(1),
                        &mut interpolated_klines
                    );
                }
                Klt::M015 =>
                    interpolate_gaps(
                        &prev,
                        &current_kline,
                        Klt::M015,
                        Duration::minutes(15),
                        &mut interpolated_klines
                    ),
                Klt::M030 =>
                    interpolate_gaps(
                        &prev,
                        &current_kline,
                        Klt::M030,
                        Duration::minutes(30),
                        &mut interpolated_klines
                    ),
                Klt::M060 =>
                    interpolate_gaps(
                        &prev,
                        &current_kline,
                        Klt::M060,
                        Duration::minutes(60),
                        &mut interpolated_klines
                    ),
                Klt::M120 =>
                    interpolate_gaps(
                        &prev,
                        &current_kline,
                        Klt::M120,
                        Duration::minutes(120),
                        &mut interpolated_klines
                    ),
                Klt::DAY =>
                    interpolate_gaps(
                        &prev,
                        &current_kline,
                        Klt::DAY,
                        Duration::days(1),
                        &mut interpolated_klines
                    ),
                // Klt::WEEK => {
                //   // Weekly interpolation would require custom logic due to variable lengths of weeks.
                //   // This is currently not implemented.
                // },
                // Monthly interpolation cannot be handled with a fixed Duration and requires separate treatment.
                _ => todo!(),
            }

            // Extend this pattern for other KLT types
            // Example for Klt::M015
            // interpolate_gaps(&prev, &current_kline, Klt::M015, Duration::minutes(15), &mut interpolated_klines);
            // And so on for M030, M060, etc.
        }

        // Always add the current kline to the results
        interpolated_klines.push(current_kline.clone());

        // Move to the next iteration
        previous_kline = Some(current_kline.clone());
    }

    interpolated_klines
}

/// Helper function to interpolate missing intervals for a given Klt and duration
/// 这个函数用于处理缺失的K线数据，例如，如果某个周期内没有数据，则需要插值填充。
///
/// 但是没有什么用了，因为chartjs chartjs 会自动处理缺失的K线数据。配置好
///
/// x: {
/// type: 'timeseries' as const,
/// }
///
/// 即可
fn interpolate_gaps(
    previous_kline: &KlineFlat,
    current_kline: &KlineFlat,
    klt: Klt,
    duration: Duration,
    interpolated_klines: &mut Vec<KlineFlat>
) {
    let gap = previous_kline.klts - current_kline.klts;
    let num_gaps = gap.num_seconds() / duration.num_seconds();

    if num_gaps > 1 {
        for n in 1..num_gaps as i32 {
            let missing_time = previous_kline.klts - duration * n;
            interpolated_klines.push(KlineFlat {
                id: None,
                klt: klt.into(),
                klts: missing_time,
                ..Default::default()
            });
        }
    }
}

#[cfg(test)]
mod test {
    use chrono::{ TimeZone, Utc };

    use crate::model::kline::Klt;

    use super::{ interpolate_missing_klines, KlineFlat };

    #[test]
    fn test_interpolate_missing_klines_m005() {
        // Sample Kline data with some gaps
        let input_klines = vec![
            KlineFlat {
                id: None,
                klt: Klt::M005,
                klts: Utc.ymd(2023, 4, 1).and_hms(9, 50, 0),
                open: 104.0,
                high: 109.0,
                low: 101.0,
                close: 106.0,
                volume: 2000,
                ..Default::default()
            },
            // Gap here: 9:40 and 9:45 Klines are missing
            KlineFlat {
                id: None,
                klt: Klt::M005,
                klts: Utc.ymd(2023, 4, 1).and_hms(9, 35, 0),
                open: 102.0,
                high: 107.0,
                low: 98.0,
                close: 104.0,
                volume: 1500,
                ..Default::default()
            },
            KlineFlat {
                id: None,
                klt: Klt::M005,
                klts: Utc.ymd(2023, 4, 1).and_hms(9, 30, 0),
                open: 100.0,
                high: 105.0,
                low: 95.0,
                close: 102.0,
                volume: 1000,
                ..Default::default()
            }
        ];

        let interpolated_klines = interpolate_missing_klines(&input_klines);

        assert_eq!(interpolated_klines.len(), 5);
        // Print out the interpolated data for verification
        for (idx, kl) in input_klines.iter().enumerate() {
            println!("[{}]{:?}", idx, kl.klts);
        }
        println!("=============");
        for (idx, kl) in interpolated_klines.iter().enumerate() {
            println!("[{}]{:?}", idx, kl.klts);
        }
    }

    #[test]
    fn test_interpolate_missing_klines_day() {
        // Input vector with some gaps in DAY intervals
        let input_klines = vec![
            KlineFlat {
                id: None,
                klt: Klt::DAY,
                klts: Utc.ymd(2023, 4, 1).and_hms(0, 0, 0),
                open: 100.0,
                high: 120.0,
                low: 90.0,
                close: 110.0,
                volume: 1000,
                ..Default::default()
            },
            KlineFlat {
                id: None,
                klt: Klt::DAY,
                klts: Utc.ymd(2023, 3, 30).and_hms(0, 0, 0),
                open: 150.0,
                high: 170.0,
                low: 140.0,
                close: 160.0,
                volume: 1500,
                ..Default::default()
            }
        ];

        // Call the function under test
        let interpolated_klines = interpolate_missing_klines(&input_klines);

        assert_eq!(interpolated_klines.len(), 3);
        // Print out the interpolated data for verification
        for (idx, kl) in input_klines.iter().enumerate() {
            println!("[{}]{:?}", idx, kl.klts);
        }
        println!("=============");
        for (idx, kl) in interpolated_klines.iter().enumerate() {
            println!("[{}]{:?}", idx, kl.klts);
        }
    }
}
